package hu.elte.inf.holiuml.model;

import hu.elte.inf.holiuml.gui.ClassNodeOptionsDialog;
import hu.elte.inf.holiuml.gui.RelationEdgeOptionsDialog;
import hu.elte.inf.holiuml.gui.HoliUML;
import hu.elte.inf.holiuml.gui.OptionsDialog;
import hu.elte.inf.holiuml.gui.RepositoryDialog;

import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.util.Vector;

import javax.swing.AbstractAction;
import javax.swing.JMenu;
import javax.swing.JMenuItem;

/**
 * @author Csaba Hoch
 */
public class ClassDiagram extends Diagram {
	private Vector<ClassNode> classNodes = new Vector<ClassNode>();
	private Vector<RelationEdge> relationEdges = new Vector<RelationEdge>();

	/** 
	 * Class constructor
	 */
	public ClassDiagram() {
	}

	@Override
	public void createMenu(JMenu menu) {
		menu.setText("Class diagram");

		menu.add(new JMenuItem(new AbstractAction("New class node") {
			public void actionPerformed(ActionEvent e) {
				createNewClassNode();
			}
		}));
		menu.add(new JMenuItem(new AbstractAction("New relation edge") {
			public void actionPerformed(ActionEvent e) {
				main.getCanvas().createNewEdge(EdgeType.RELATION);
			}
		}));
		
		menu.add(new JMenuItem(new AbstractAction("Repository of Classes") {
			public void actionPerformed(ActionEvent e) {
				browserInRepository();
			}
		}));
		
		super.createMenu(menu);
	}

	public void draw(Graphics g) {
		drawDrawables(g, classNodes);
		drawDrawables(g, commentNodes);
		drawDrawables(g, relationEdges);
		drawDrawables(g, commentEdges);
	}

	@Override
	public Node nodeUnderPoint(Point p) {
		Node node = null;
		node = nodeUnderPoint(commentNodes, p);
		if (node != null) {
			return node;
		}
		node = nodeUnderPoint(classNodes, p);
		if (node != null) {
			return node;
		}
		return null;
	}

	@Override
	public Edge edgeUnderPoint(Point p) {
		Edge edge = null;
		edge = edgeUnderPoint(relationEdges, p);
		if (edge != null) {
			return edge;
		}
		edge = edgeUnderPoint(commentEdges, p);
		if (edge != null) {
			return edge;
		}
		return null;
	}

	/**
	 * Creates a new class node.
	 */
	public void createNewClassNode() {
		ClassNodeOptionsDialog optDlg = new ClassNodeOptionsDialog(super.main, null);
		if (optDlg.getButtonCode() == OptionsDialog.OK) {
			getClassNodes().add(optDlg.createData());
			main.getCanvas().repaint();
		}
	}
	
	public void browserInRepository()
	{
		RepositoryDialog optDlg = new RepositoryDialog(super.main, null);
		if (optDlg.getButtonCode() == OptionsDialog.OK) {
			getClassNodes().add(optDlg.createData());
			main.getCanvas().repaint();
		}
	}
	
	@Override
	public void createNewEdge(Node node1, Node node2, EdgeType edgeType) {
		if (edgeType == EdgeType.RELATION) {
			try {
				ClassNode classNode1 = (ClassNode) node1;
				ClassNode classNode2 = (ClassNode) node2;
				RelationEdgeOptionsDialog edgeDlg = new RelationEdgeOptionsDialog(super.main,
						classNode1, classNode2, classNodes);
				if (edgeDlg.getButtonCode() == OptionsDialog.OK) {
					getRelationEdges().add(edgeDlg.createRelation());
					main.getCanvas().repaint();
				}
			} catch (Exception e) {
				System.out.println(e);
			}
		} else {
			super.createNewEdge(node1, node2, edgeType);
		}
	}

	public Vector<ClassNode> getClassNodes() {
		return classNodes;
	}

	public void setClassNodes(Vector<ClassNode> classNodes) {
		this.classNodes = classNodes;
	}

	public Vector<RelationEdge> getRelationEdges() {
		return relationEdges;
	}

	public void setRelationEdges(Vector<RelationEdge> relationEdges) {
		this.relationEdges = relationEdges;
	}

	public void removeClassNode(ClassNode classNode){
		RelationEdge relationEdge = null;
		while ( (relationEdge = searchRelationEdgeByClassNode(classNode))!= null){
			relationEdges.removeElement(relationEdge);
		}
		classNodes.removeElement(classNode);
		main.getCanvas().repaint();
	}
	
	public RelationEdge searchRelationEdgeByClassNode(ClassNode classNode){
		RelationEdge relationEdge = null;
		int relationEdgeIndex = 0;
		while (relationEdgeIndex < relationEdges.size() &&
				(ClassNode)relationEdges.elementAt(relationEdgeIndex).getNodeBegin() != classNode &&
				(ClassNode)relationEdges.elementAt(relationEdgeIndex).getNodeEnd() != classNode	){
			relationEdgeIndex++;
		}		
		if (relationEdgeIndex != relationEdges.size()){
			relationEdge = relationEdges.elementAt(relationEdgeIndex); 
		}
		return relationEdge;
	}
	
	/**
	 * Removes the first (lowest-indexed) occurrence of the argument from this vector.
	 * 
	 * @param relationEdge what we want to delete
	 */
	public void removeRelationEdge(RelationEdge relationEdge )
	{
		relationEdges.removeElement(relationEdge);
		main.getCanvas().repaint();
	}
    
	/**
	 * Deletes the component at the specified index.
	 * 
	 * @param index index of component what we want to delete.
	 */
    public void removeRelationEdgeAt(int index )
    {
    	relationEdges.removeElementAt(index);
	}

}
